package com.example.leetcode.juc;

import com.example.leetcode.juc.common.HtmlParser;
import com.example.leetcode.juc.common.HtmlParserImpl;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * // This is the HtmlParser's API interface.
 * // You should not implement it, or speculate about its implementation
 * interface HtmlParser {
 * public List<String> getUrls(String url) {}
 * }
 */
class Solution1242 {

    BlockingQueue<String> outQueue = new LinkedBlockingQueue<>();
    BlockingQueue<String> inQueue = new LinkedBlockingQueue<>();
    String host;

    public List<String> crawl(String startUrl, HtmlParser htmlParser) {
        host = getHost(startUrl);
        ConcurrentHashMap<String, Integer> result = new ConcurrentHashMap<>();
        outQueue.add(startUrl);
        while (outQueue.size() > 0) {
            int levelSize = outQueue.size();
            CountDownLatch count = new CountDownLatch(levelSize);
            for (int i = 0; i < levelSize; i++) {
                Runnable task = () -> {
                    try {
                        String url;
                        url = outQueue.take();
                        result.putIfAbsent(url, 0);
                        List<String> urls = htmlParser.getUrls(url);
                        for (String s : urls) {
                            if (!valid(s, result)) {
                                continue;
                            }
                            inQueue.put(s);
                        }
                        count.countDown();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                };
                Thread thread = new Thread(task, "thread-" + i);
                thread.start();
            }
            try {
                count.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if (inQueue.size() > 0) {
                outQueue.addAll(inQueue);
                inQueue.clear();
            }

        }

        return new ArrayList<>(result.keySet());
    }

    public String getHost(String startUrl) {
        return startUrl.substring(7).split("/")[0];
    }

    private boolean valid(String s, ConcurrentHashMap<String, Integer> visited) {
        if (!this.host.equals(getHost(s))) {
            return false;
        }
        return visited.get(s) == null;
    }
}

public class leetcode1242 {
    public static void main(String[] args) {

        String[] urls = {
                "http://news.yahoo.com",
                "http://news.yahoo.com/news",
                "http://news.yahoo.com/news/topics/",
                "http://news.google.com",
                "http://news.yahoo.com/us"
        };
        int[][] edges = {{2, 0}, {2, 1}, {3, 2}, {3, 1}, {0, 4}};
        String startUrl = "http://news.yahoo.com/news/topics/";

        Solution1242 solution1242 = new Solution1242();
        System.out.println(solution1242.crawl(startUrl, new HtmlParserImpl(urls, edges)));
    }
}
